// // *********************************第五节 ES6字符串模板的用法********************

let Es5String = 'sunkening';
let blog = "我是你的新朋友"+Es5String+"大家好。";
console.log(blog);
let Es6string = 'sunkening';
let blog6 = `我是你的新朋友${Es6string}家好`;
let b = `<b>非常高兴你能看到这篇文章</b>，我是你的老朋友${Es5String}。<br/>这节课我们学习字符串模版。`
console.log(blog6);
console.log(b);
let a = 1;
let c= 2;
let d = `${a+c}`;
console.log(d);


// *********************************第六节 ES6数字操作********************

// 1、二级制声明 二进制的英文单词是Binary,二进制的开始是0（零），然后第二个位置是b（注意这里大小写都可以实现），然后跟上二进制的值就可以了。
let binary =  0b010101;
console.log(binary);
// 2、把进制 Octal
let Octal = 0o666;
console.log(Octal);

let a2 = 11/3;
console.log(Number.isFinite(a2)); //true
console.log(Number.isFinite('sukneing')); //false
console.log(Number.isFinite(NaN));// false
console.log(Number.isFinite(undefined));//false
// 3、 判读NaN的方法
console.log(Number.isNaN(NaN)); //不是数的为true
console.log(Number.isNaN(1));  //返回false
// 4、判断是否为整数
console.log(Number.isInteger(12));//true
console.log(!Number.isInteger(12));//false
// 5、判断浮点数
console.log(!Number.isInteger(12));//false

// 6、数字间的转换
console.log(Number.parseInt(12.1));//12
console.log(Number.parseFloat(12));//
// 7、取值范围
let sunkening = Math.pow(2,53)-1; //最大值
console.log(sunkening);
//8、最大安全整数
console.log(Number.MAX_SAFE_INTEGER);//9007199254740991
console.log(Number.MIN_SAFE_INTEGER);//-9007199254740991
//9、判断是否安全整数     严禁的写法：如果超过安全整数的话应当转换为字符串
console.log(Number.isSafeInteger(sunkening)); //true


// ******************第7节：ES6中新增的数组知识（1）********************************

    // 1、JSON数组格式转换
        let json = {
            "0":"1",
            "1":"2",
            "2":"3",
            length:3
        }
        let arr1 = Array.from(json);
        console.log(arr1); //["1", "2", "3"]

    // 2、Array.of();
    
        let arr2 = Array.of(1,2,3,4);
        console.log(arr2); // [1, 2, 3, 4]

    // 3、find() 实例方法  //找到则停止查找，返回找到的第一个值  否则 undefined
    let arr3 = [1,3,4,4,5,5,6,7,7,8,9];
    console.log(arr3.find(function(val,index,arr){
        return val >9 
    }))


    //*************************第8节：ES6中新增的数组知识（2）****************************************


    // 1、fill() 实例方法
    let arr4 = [1,23,4,5,5,6];
    arr4.fill('djningls',2,5); //替换值，替换开始的index，结束的index
    console.log(arr4);
    // 2、数组的遍历 for of
        let arr5 = [1,23,4,5,55];
        for(let val of arr5){
            console.log(val);
        }
    //3、 for…of数组索引:有时候开发中是需要数组的索引的
        let arr6 = ['dj','sun','kn'];
        for(let index of arr6.keys()){
            console.log(index);
        }
    //4、同时输出数组的内容和索引：我们用entries()这个实例方法
        let arr7=['s','k','n'];
        for(let [index,val] of arr7.entries()){
            console.log(`${index}==>${val}`);
        }
    //5、我们用entries()这个实例方法
        let arr8 = ['d','j','n','i','n','g'];
        let list = arr8.entries();
        console.log(list.next().value);
        console.log(list.next().value);
        console.log(list.next().value);
        console.log(list.next().value);


    //6、*******************************第9节：ES6中的箭头函数和扩展************************* 

    // 1、ES5的常用函数  
    
    // 严格模式 1、Es5 的严格模式只能写在文章的开头、
    // 2、ES6 可以写在任何位置，当写在函数内部的时候，参数不能有默认值否则会报错如下
    // Uncaught SyntaxError: Illegal 'use strict' directive in function with non-simple parameter list

        function add1(m=1,n){
            // 'use strict'  //这里有默认值不能写严格模式
            return m+n;
        }
        console.log(add1(3,4)); // 7
 
        function add2(m,n){
            'use strict'  //可以正常些严格模式
            return m+n;
        }
        console.log(add2(1,2)); //3

    // 主动抛出异常
        function add3(m,n){
            if(m==0){
                // throw new Error("m不能小于0");
            }
            return m+n;
        }
        console.log(add3(0,1));
// 2、箭头函数
    let add4 = (m=1,n)=> m+n;
    console.log(add4(1,2));
    // 使用{}
    let add5 = (m,n)=>{
        console.log(m+n);
    }
    add5(2,2);


    // *******************************第10节：ES6中的函数和数组补漏***********************
    // 1、对象的函数解构
        let obj = {
            'age':18,
            'name':'jack'
        }
        //普通写法
    //    function objJg({age,name}){
    //      console.log(age);
    //      console.log(name);
    //    } 
        // 箭头函数写法
        let objJg = ({age,name})=>{
            console.log(age);
            console.log(name);
        }
       objJg(obj)// 注意点就是解构函数的参数要和队形的key 值保持一致
    // 2、数组的函数解构
       let arr9 = ['age','naem','sex','like'];
    
       function arrJG(j,k,l,n){
           console.log(j);
           console.log(k);
           console.log(n);
            // console.log(`${j}${k}${l}${n}`);
       }
       arrJG(...arr9); //注意要用 ... 进行数组解构

    // 3、in 的用法
       let obj2 = {
           'age':18,
           'sex':'man'
       }
       console.log("age" in obj2);//true
       console.log('like' in obj2);//false

    // 4、用in 进行数组的判断
       let arr10 = [1,2,3,4,5,6];
       let arr11 = [,,,,,,];
       console.log(arr11.length);//显示长度为6
       console.log(0 in arr11); //false
       console.log(0 in arr10);//true

    // 5、 数组遍历
        // 1、forEach
            let arr12 = ['age','name','sex','city'];
            // arr12.forEach((val,index)=>console.log(val,index));
               arr12.forEach((val,index)=>{
                   console.log(val,index);
               })
        // 2、数组遍历 filter
               arr12.filter(x=>console.log(x));

        // 3、数组遍历 some
               arr12.some((val,index)=>console.log(val,index));
        // 4、数组遍历 map  起到遍历的作用
               console.log(arr12.map(x=>'web')); //将数组中的所有元素替换为web

    // 6、 数组转字符串
        // 1、toString方法
            let arr13 = [1,2,3,4,5,5,67];
            console.log(arr3.toString());
        // 2、join('|')方法用什么进行分割
            let arr14 = [1,2,3,4,5,5,67];
            console.log(arr14.join("*"));//1*2*3*4*5*5*67


    //*******************第11节：ES6中对象*******************

    //1、 对象的赋值 ES5
    let name = 'jack';
    let age = '18';
    let obj3 = {
        name:name,
        age:age
    }
     // 对象的赋值 ES6
    let name1='jack';
    let age1 = 12;
    let obj4 = {name1,age1}
    console.log(obj4);

    // 2
// 2、key 值的构建   使用场景 key值不固定从后台读取过来的，我们只知道value值
    let key = 'key';
    let obj5 = {
        [key]:"12"
    }
    console.log(obj5);
// 3、自定义对象的方法
    let obj6 = {
        add:function(k,n){
            return k+n;
        },
    }
    console.log(obj6.add(1,2))

// 4、ES6 对obj 的新方法和新特性
    // Object.is()判断对象是否相等

    var obj7 = {name:'string'};
    var obj8 = {name:'string'};
    console.log(obj7.name === obj8.name);
    console.log(Object.is(obj8.name,obj7.name));

// 5、Object.assign(  )合并对象
    let obj10 = {"age":18};
    let obj11 = {"sex":'女'};
    console.log(Object.assign(obj10,obj11));

//******************第12节：Symbol在对象中的作用   ******* */
// 1、js 中常见的数据类型有哪些
    let  str = new String();
    let Bolean = new Boolean();
    let number = new Number();
    let objtype = new Object();
    let arrType = new Array();  
    let sy = Symbol();
    console.log(typeof(sy));

//2、symbol的打印
    let sym = Symbol("skn");
    console.log(sym);//在控制台显示红色
    console.log(sym.toString()); //显示正产的字符串

// 2、Symbol在对象中的应用
    let symbol1 = Symbol();
    let obj12  = {
        [symbol1]:'12'
    }
    console.log(obj12[symbol1]); //Symbol 在对象中获取数据只能使用[] 不能用点来获取
    obj12[symbol1] = 'sunkn12';

//3、Symbol对象元素的保护作用

    // *******没有进行对象保护的
    let obj15 = {
        'age':'12',
        'sex':'女',
        'name':'sukening'
    }
    for(let item in obj15){
        console.log(obj15[item]);
    }
    // ******Symbol进行数据保护的   注意symbol类型的数据在循环中是读取不到的所以起到保护的作用
    let obj16 = {"age":'12','name':'sunkn'}
    let sex = Symbol();//设置一个symbol类型的变量
    obj16[sex] = '女'; //为symbol进行赋值
    for(let inde in obj16){
        console.log(obj16[inde]);
    }




    // ***********************************第13节：Set和WeakSet数据结构 *************************************
//  1、set
        let setArr = new Set(['usnk','name','age','age']);
        console.log(setArr);//重复的数据会忽略
        setArr.add('djningls');//添加
        console.log(setArr);
        setArr.delete('name');
        console.log(setArr);
        setArr.has("name");//false
        // setArr.clear();
        console.log(setArr);
        //for of 循环
        for(let index1 of setArr){
            console.log(index1);
        }
        // 获取set 的长度 size 属性
        console.log(setArr.size);

        // forEach 循环
        setArr.forEach((x)=>console.log(x+"dfd"));
// 2、WeakSet 的声明 这里需要注意的是，如果你直接在new 的时候就放入值，将报错
        let Weakobj = new WeakSet();
        let obj13 = {'name':"sunkn",'age':"12"};
        let obj17 = {'sex':'女'}
            Weakobj.add(obj13);
            Weakobj.add(obj17);
        console.log(Weakobj);


// ******************************************第14节：map数据结构  ***************************************************************************************


        // 1、json 和 Map 的对比   map的灵活性和效率都高过json格式
            let json1 = {
                name:'sunkn',
                age:'12'
            }
            console.log(json1.name);//内部回循环查找，导致效率较低

            let map = new Map();
            
            map.set("json",json1);
            console.log(map);
            map.set('age','12'); //增加
            console.log(map);
            map.delete("age"); //删除
            map.get('json'); //获取
            console.log(map.size);//长度
            console.log(map.has("json")); //true 
            map.clear(); //清空map



//*******************************第15节：用Proxy进行预处理******************************************************************************************************** 

// 如果你学过Vue的课程，一定会知道钩子函数，那如果你并没有学习Vue，那我这里给你简单解释一下什么是钩子函数。
// 当我们在操作一个对象或者方法时会有几种动作，比如：在运行函数前初始化一些数据，在改变对象值后做一些善后处理。这些都算钩子函数，
// Proxy的存在就可以让我们给函数加上这样的钩子函数，你也可以理解为在执行方法前预处理一些代码。你可以简单的理解为他是函数或者对象的生命周期。

// 1、首先我们来创建一个对象
    let obj18 = {
        add:function(val){
            return val+100;
        },
        name:"sunkkn"
    }
    console.log(obj18.add(100));
    console.log(obj18.name);
// 2、我们来创建一个Proxy  //参数为两个对象 1、对象方法 2、 要进行预处理的对象方法：{set，get，apply}，apply为预处理方法的操作
   //   Proxy({},{})


    let target = {
        add:function(val){
            return val+100;
        },
        name:'sunkn'
    }
    //预处理对象
    let handler = {
        // target：得到的目标值 
        //key：目标的key值，相当于对象的属性
        // property：这个不太常用，用法还在研究中，还请大神指教。
        get:function(target,key,property){
            console.log("Proxy in get 方法");
            return target[key];
        },
        // target:目标值。
        // key：目标的Key值。
        // value：要改变的值。
        // receiver：改变前的原始值。
        set:function(target,key,value,receiver){
            console.log("Proxy in set 方法");
            return target[key] = value;
        },
        apply:function(target,ctx,args){
            console.log('do apply');
            return Reflect.apply(...arguments);
        }
    }
    let proxy= new Proxy(target,handler);
    proxy.name; //此时会调用 handler对象中的get方法
    proxy.name = "孙克宁"; //此时会调用 handler对象中的 set方法
    proxy.add(100);//此时会调用 handler对象中的 apply方法




    // ***********************第16节：promise对象的使用********************************************************************
    //promise执行多步操作非常好用，那我们就来模仿一个多步操作的过程，那就以吃饭为例吧。要想在家吃顿饭，是要经过三个步骤的。
    // 1、洗菜做饭。
    // 2、坐下来吃饭。
    // 3、收拾桌子洗碗。 在ES5中我们处理这种流程都是采用回掉的方式进行完成的。

        let state = 1; //用来进行回到是否成功的判断条件   resolve为正取完成的回调、reject失败时的回调

        let step1 = (resolve,reject)=>{
            console.log("1、正在进行洗菜做饭");
            if(state == 1){
                resolve ("洗菜做饭完成");
            }else{
                reject("洗菜出错");
            }
        };
        let step2 = (resolve,reject)=>{
            console.log("2、正在吃放中");
            if(state == 1){
                resolve("2、吃饭完成");
            }else{
                reject("吃饭错误");
            }
        };
        let step3 = (resolve,reject)=>{
            console.log("3、正在收拾桌子洗碗");
            if(state == 1){
                resolve('3、收拾桌桌子、洗碗完成')
            }else{
                reject("洗碗出错");
            }
        };

        new Promise(step1).then(function(val){ //注意val值为上一个方法resolve中传过来的数据值
                // alert(val);
               return new Promise(step2);//不要忘记return
        }).then(function(val){
                // alert(val);
                return new Promise(step3);//不要忘记return
        }).then(function(val){
                // alert(val);
        })


// *****************************************第17节：class类的使用*******************************************************

// 1、类的声明
    
    class person{
        setName(name){
            console.log(name);
            this.name = name;
        }
    }
    let person1 = new person;
    person1.setName("孙克宁");

// 2、类的多方法声明

    class Coder{
        setName(name){
            console.log(name);
            this.name = name;
        }
        getName(){
            return this.name
        }
    }
    let coder = new Coder;
    coder.setName("sunkening");
    console.log(coder.getName());

// 3、类的传参 使用constructor

    class Coder1{
        getName(){
            return this.name;
        }
        setName(name){
            this.name = name;
        }
        //构造器
        constructor(age,name){
            this.name = name;
            this.age = age;
        }
    }

    let Coder1 = new Coder1(18,"孙克宁"); // 类的实例化
    Coder1.getName();

// 4、类的继承

    class coder2 extends Coder1{

    }
   let coders =  new coder2; //子类实例化
   coders.setName("sonClass");
   console.log(coders.getName());//子类调用父类的方法
